/*
 * $Id$
 */
package org.crazydays.wowarmory;


import java.io.InputStream;
import java.io.IOException;
import java.net.URI;
import java.text.ParseException;
import java.util.Properties;
import java.util.List;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.httpclient.Header;

import org.crazydays.text.Argument;
import org.crazydays.text.Arguments;
import org.crazydays.text.ArgumentException;
import org.crazydays.wowarmory.page.CharacterReputationPageImpl;
import org.crazydays.wowarmory.page.CharacterSheetPageImpl;
import org.crazydays.wowarmory.data.NameData;

/**
 * WowArmory
 */
public class WowArmory
{
	/** log */
	protected static Log LOG = LogFactory.getLog(WowArmory.class);

	/** property: wowarmory base uri */
	public final static String PROP_BASE_URI = "wowarmory.baseUri";

	/** property: properties loaded */
	protected final static String PROP_PROPERTIES_LOADED = "propertiesLoaded";

	/** properties */
	protected static Properties properties = new Properties();

	/** argument string: action */
	public final static String ARG_ACTION_STRING = "action";

	/** argument character: a */
	public final static Character ARG_ACTION_CHARACTER = 'a';

	/** argument string: base uri */
	public final static String ARG_BASE_URI_STRING = "baseUri";

	/** argument character: base uri */
	public final static Character ARG_BASE_URI_CHARACTER = 'b';

	/** argument string: name */
	public final static String ARG_NAME_STRING = "name";

	/** argument character: name */
	public final static Character ARG_NAME_CHARACTER = 'n';

	/** argument string: realm */
	public final static String ARG_REALM_STRING = "realm";

	/** argument character: realm */
	public final static Character ARG_REALM_CHARACTER = 'r';

	/** argument string:  */
	public final static String ARG__STRING = "";

	/** argument character:  */
	public final static Character ARG__CHARACTER = '\0';

	/** action: character sheet */
	public final static String ACT_CHARACTER_SHEET = "character-sheet";

	/** action: character reputation */
	public final static String ACT_CHARACTER_REPUTATION = "character-reputation";

	/**
	 * Get property.
	 *
	 * @param property Property
	 * @return Value
	 */
	public static String getProperty(String property)
	{
		String loaded = properties.getProperty(PROP_PROPERTIES_LOADED);
		if (loaded == null || loaded.trim().length() == 0 ||
			loaded.equals("false")) {
			loadProperties();
		}

		return properties.getProperty(property);
	}

	/**
	 * Load properties.
	 */
	public static void loadProperties()
	{
		properties.setProperty(PROP_PROPERTIES_LOADED, "true");

		InputStream inputStream = Thread.currentThread().
			getContextClassLoader().getResourceAsStream(
				"wowarmory.properties");
		if (inputStream == null) {
			return;
		}

		try {
			properties.load(inputStream);
		} catch (IOException e) {
			LOG.error("Unable to load properties", e);
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException f) {
					LOG.error("Unable to close inputStream", f);
				}
			}
		}
	}

	/**
	 * Main
	 *
	 * @param args Arguments
	 */
	public final static void main(String[] args)
	{
		Arguments arguments = null;
		try {
			// construct arguments
			arguments = getNewArguments();

			// parse arguments
			arguments.parse(args);
			arguments.validate();

			String action = arguments.getArgument(ARG_ACTION_STRING).getValue();
			String baseUri = arguments.getArgument(ARG_BASE_URI_STRING).getValue();
			String name = arguments.getArgument(ARG_NAME_STRING).getValue();
			String realm = arguments.getArgument(ARG_REALM_STRING).getValue();

			if (baseUri == null) {
				baseUri = getProperty(PROP_BASE_URI);
			}

			// construct armory
			WowArmory wowArmory = new WowArmory(baseUri);

			IPage page = null;
			if (action.equals(ACT_CHARACTER_SHEET)) {
				page = wowArmory.getCharacterSheet(name, realm);

				NameData nameData = page.getData(new NameData());
				System.out.println("nameData: " + nameData.getName());
			} else if (action.equals(ACT_CHARACTER_REPUTATION)) {
				page = wowArmory.getCharacterReputation(name, realm);
			} else {
				throw new ArgumentException("Unknown action").
					setArgument(arguments.getArgument(ARG_ACTION_STRING));
			}

//			String pageString = new String(page.getBytes());
//			System.out.println(pageString);
		} catch (WowArmoryException e) {
			LOG.error(e);
		} catch (ArgumentException e) {
			LOG.error(e);
			System.err.println("Usage: " + arguments);
		} catch (ParseException e) {
			System.err.println("Usage: " + arguments);
			LOG.error(e);
		}
	}

	/**
	 * Get new arguments.
	 *
	 * @return Arguments
	 * @throws ArgumentExcpetion
	 */
	public final static Arguments getNewArguments()
		throws ArgumentException
	{
		// construct arguments
		Arguments arguments = new Arguments();
		Argument argument = null;

		// action
		argument = new Argument(ARG_ACTION_STRING,
			ARG_ACTION_CHARACTER, true);
		argument.addOption(ACT_CHARACTER_SHEET);
		argument.addOption(ACT_CHARACTER_REPUTATION);
		arguments.addArgument(argument);

		// base url
		argument = new Argument(ARG_BASE_URI_STRING,
			ARG_BASE_URI_CHARACTER, false);
		arguments.addArgument(argument);

		// name
		argument = new Argument(ARG_NAME_STRING,
			ARG_NAME_CHARACTER, false);
		arguments.addArgument(argument);

		// realm
		argument = new Argument(ARG_REALM_STRING,
			ARG_REALM_CHARACTER, false);
		arguments.addArgument(argument);

		return arguments;
	}

	/** base uri */
	protected URI baseUri = null;

	/** wow armory http client */
	WowArmoryHttpClient client = new WowArmoryHttpClient();

	/**
	 * WowArmory constructor.
	 *	
	 * @param arguments Arguments
	 */
	public WowArmory(String baseUri)
	{
		setBaseUri(baseUri);
	}

	/**
	 * Set base uri.
	 *
	 * @param baseUri
	 */
	public void setBaseUri(URI baseUri)
	{
		if (baseUri == null) {
			throw new IllegalArgumentException("baseUri == null");
		}

		this.baseUri = baseUri;
	}

	/**
	 * Get base uri.
	 *
	 * @return Base uri
	 */
	protected URI getBaseUri()
	{
		return baseUri;
	}

	/**
	 * Get client.
	 *
	 * @return WowArmoryHttpClient
	 */
	protected WowArmoryHttpClient getClient()
	{
		return client;
	}

	/**
	 * Set base uri.
	 *
	 * @param baseUri Base uri
	 */
	public void setBaseUri(String baseUri)
	{
		if (baseUri == null) {
			throw new IllegalArgumentException("baseUri == null");
		}

		setBaseUri(URI.create(baseUri));
	}

	/**
	 * Get character sheet.
	 *
	 * @param name Name
	 * @param realm Realm
	 * @return CharacterSheetPageImpl
	 */
	protected CharacterSheetPageImpl getCharacterSheet(String name, String realm)
		throws WowArmoryException
	{
		CharacterSheetPageImpl page = new CharacterSheetPageImpl(
			getBaseUri(), name, realm);

		return getClient().getPage(page);
	}

	/**
	 * Get character reputation.
	 *
	 * @param name Name
	 * @param realm Realm
	 * @return CharacterReputationPageImpl
	 * @throws WowArmoryException
	 */
	protected CharacterReputationPageImpl getCharacterReputation(
		String name, String realm)
		throws WowArmoryException
	{
		CharacterReputationPageImpl page = new CharacterReputationPageImpl(
			getBaseUri(), name, realm);

		return getClient().getPage(page);
	}
}
